Most likely, it's done like sbi suggests, so the interpreter's struct would look more like:
struct Object
{
ubyte type;
void* value;
};
The actual value would be allocated somewhere on the heap, and when the object was constructed, the interpreter would note the type in ubyte type. Later, functions would note the type using object.type and alias the value to that type, or just assume that it was the correct type, like this:
useObjectAsString(Object toUse)
{
char* data = (char*)toUse.value;
}
If you just have a few types you want to implement, you could also try using a union.