It seems that adjusting for padding is key here: each cell has 3px padding on both the left and right, so you must account for an additional 6px in the width:
$t.find('tr:first th').each(function(){cols.push($(this).width()+6);});
Otherwise, cells containing only one word may stretch the width slightly to accommodate the word, while other cells will adjust by becoming a bit narrower. This discrepancy in cell widths is caused by differing content in the header and body sections.
UPDATE: In Firefox, you'll also need to expand the table itself to ensure all cells fit. After calculating the column widths, add:
var actualWidth = $t.width()+cols.length*6;
$t.width( actualWidth );
Then, adjust the wrapper element as follows:
$wrap.css({width:actualWidth,height:o.height,overflow:'auto'});
UPDATE 2: To enable simultaneous scrolling for both the header and body, wrap them together within an outer div that manages the scrolling behavior.
var $outerWrap = $( '<div>' ).css( {width:"300px", overflow:'auto' } );
var $wrap=$('<div>').css(
{ width:actualWidth,height:o.height,"overflow-y":'auto', "overflow-x":'hidden' }
);
$firstRow.wrap( $outerWrap );
$firstRow.after( $wrap );
$wrap.append( $t );
See a demo here: http://jsfiddle.net/YcRTz/2/