However! When the rubber meets the road, there has to be some kind of bit-level representation somewhere. In Smalltalk, the VM hides these details from the programmer, who gets to reason uniformly about objects without caring about their representation. Specifically, Smalltalk VMs often use pointer tagging [0] just like lots of other dynamic languages do.
[0] Lots of interesting stuff on pointer tagging here: https://www.snellman.net/blog/archive/2017-09-04-lisp-number...
(Internally, they are actually represented as 31-bit numbers for performance reasons)
Floats are also boxed automagically in a 64-bit entry.
For example in Eiffel is even more complex, when you create a class it is possible to tag it with the default behaviour (reference or value), which you can later override when declaring variables or type parameters in generic code.