It actually seems like the query in the original question only requires a very small change for getting the actual most recent record for each thread.
- drop the sender_id in the subquery's GROUP BY fields
- drop the *pm_data.sender_id = deriv1.sender_id* in the ON clause
SELECT pm_info.is_read, sender.usrFirst as sender_name, pm_data.date_sent, pm_data.title, pm_data.thread_id, pm_data.id as dataid, thread_max_date_sent
FROM pm_info
INNER JOIN pm_data ON pm_info.message_id = pm_data.id
INNER JOIN tblUsers AS sender ON pm_data.sender_id = sender.usrID
INNER JOIN (SELECT thread_id, /*sender_id,*/ MAX(date_sent) AS thread_max_date_sent
FROM pm_data GROUP BY thread_id /*, sender_id*/) deriv1
ON pm_data.thread_id = deriv1.thread_id AND pm_data.date_sent = deriv1.thread_max_date_sent /*AND pm_data.sender_id = deriv1.sender_id*/
WHERE pm_info.receiver_id = '$usrID'
ORDER BY deriv1.thread_max_date_sent DESC
As a side note: if possible, look for the max messageID in that subquery instead of max(date_sent)