You can do it, but you have add some redundant code to make it happen.
The verify_id() function is what generates that error, so if you want to preempt it you have to throw in a check before it gets called and override what it would've done.
Add a plugin that is triggered by showthread_start
Code:
if (!$check = $vbulletin->db->query_first('SELECT threadid FROM ' . TABLE_PREFIX . 'thread WHERE threadid = ' . $vbulletin->db->escape_string( $vbulletin->GPC['threadid']) ))
{
// If using fastcgi this is the 404 header
// header("Status: 404 Not Found");
// otherwise this is the standard 404
header("HTTP/1.0 404 Not Found");
}
If you don't add an exit after the header you'll throw the 404 instead of the 200, but still show the normal page.
If you want to actually pass the handling to your webserver's error handling document you'd need to either include the error document after it and exit, or similar.