Usually when dealing with something like 'Union(BigThing, SmallThing)' you have to allocate sizeof(BigThing + tag) in most places anyway because you need to statically know the size so that it can be a struct/array member, live on the stack etc.
The only time you can get away with only allocating the 'real' size is if you're sticking it in its own separte memory allocation and using a pointer to refer to it in the aforementioned contexts. Which, to be fair, is a sensible thing to do if BigThing is very big, as opposed to just 'on the bigger end of sane struct sizes'.
To clarify I'm talking about what you'd do in a language implementation where the actual memory layout is opaque to userspace and bit twiddling optimizations aren't making things harder to understand for everything, not what you'd do when writing handwritten C code or an api where you expect people to access the memory directly. This isn't unheard of - e.g. from my research Swift does it, some C++ stdlib implementations do it.
(Related - the rest of the bag of weird tricks that Rust and Swift and presumably other languages use to optimize enum/union layout are pretty interesting - the tag bits actually take up no extra space in many cases).