bytes - true bytes as in 3.x, e.g. bytes( "foobar", encoding) is valid, but not valid in cpython 2.x
str, unicode - true unicode (again as in 3.x), exactly the same type
>>> type(u'')
<type 'str'>
>>> type('')
<type 'str'>
>>> isinstance('',unicode)
True

The following is for 2.7 iron only.
json.dumps returns str (as per 2.7 api spec). If the params (default) request encoded str, it will be encoded. That is, the values will be provided in 16-bit unicode, but each char point is in the byte range (0-255). Now to pass it into zmq.send, I have to collapse it into true bytes and that is the bytes(s, 'iso-8859-1') aka. bytes(s, 'latin-1').

If I think about it, ideally it should go down in such a form (encoded str) until it hits ctypes, where the memory copy is obligatory. But there are parameter checking and asserts all over the place.